//
//  ViewController.swift
//  swift-learning
//
//  Created by aron on 2018/5/16.
//  Copyright © 2018年 aron. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    var tableView : UITableView?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
        struct MarkStruct {
            var mark: Int
            
            init(mark: Int) {
                self.mark = mark
            }
        }
        
        struct studentMarks {
            var mark1 = 100
            var mark2 = 78
            var mark3 = 98
        }
        let marks = studentMarks()
        print("Mark1 是 \(marks.mark1)")
        print("Mark2 是 \(marks.mark2)")
        print("Mark3 是 \(marks.mark3)")
        
        // 结构体的拷贝
        // 结构体实例总是通过值传递来定义你的自定义数据类型。
        let aMark = MarkStruct(mark: 98)
        print(aMark.mark)
        
        var bMark = aMark
        bMark.mark = 90
        print(bMark.mark)
        
        let spClass1 = SampleClass(s: "Hello")
        let spClass2 = SampleClass(s: "Hello")
        
        if spClass1 === spClass2 {// false
            print("引用相同的类实例 \(spClass1)")
        }
        
        if spClass1 !== spClass2 {// true
            print("引用不相同的类实例 \(spClass2)")
        }
        
        
        // MARK:- 多层可选链的使用
        let john = Person()
        
        if let johnsStreet = john.residence?.address?.street {
            print("John 的地址为 \(johnsStreet).")
        } else {
            print("不能检索地址")
        }
        
        
        // MARK:- 循环引用处理
        var toc: Module?
        var list: SubModule?
        toc = Module(name: "ARC")
        list = SubModule(number: 4)
        toc!.sub = list
        list!.topic = toc
        
//        toc = nil
//        list = nil
        
        // MARK:- 闭包导致的循环引用例子
        //创建并打印HTMLElement实例
        var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
//        print(paragraph!.asHTML())
        if let prag = paragraph {
            print(prag.asHTML())
        }
        
        // HTMLElement实例将会被销毁，并能看到它的析构函数打印出的消息
        paragraph = nil
        
        
        // MARK:- 类型检查例子
        let sa = [
            Chemistry(physics: "固体物理", equations: "赫兹"),
            Maths(physics: "流体动力学", formulae: "千兆赫"),
            Chemistry(physics: "热物理学", equations: "分贝"),
            Maths(physics: "天体物理学", formulae: "兆赫"),
            Maths(physics: "微分方程", formulae: "余弦级数")]
        
        
        let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
        print("实例物理学是: \(samplechem.physics)")
        print("实例方程式: \(samplechem.equations)")
        
        
        let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
        print("实例物理学是: \(samplemaths.physics)")
        print("实例公式是: \(samplemaths.formulae)")
        
        var chemCount = 0
        var mathsCount = 0
        for item in sa {
            // 如果是一个 Chemistry 类型的实例，返回 true，相反返回 false。  相当于isKindOfClass
            if item is Chemistry {
                chemCount += 1
            } else if item is Maths {
                mathsCount += 1
            }
        }
        
        // 使用if-let和as?判断类型
        for item in sa {
            // 如果是一个 Chemistry 类型的实例，返回 true，相反返回 false。  相当于isKindOfClass
            if let _ = item as? Chemistry {
                chemCount += 1
            } else if let _ = item as? Maths {
                mathsCount += 1
            }
        }
        
        print("化学科目包含 \(chemCount) 个主题，数学包含 \(mathsCount) 个主题")
        
        // Any可以表示任何类型，包括方法类型
        var exampleany = [Any]()
        exampleany.append(12)
        exampleany.append(3.14159)
        exampleany.append("Any 实例")
        exampleany.append(Chemistry(physics: "固体物理", equations: "兆赫"))
        
        // 使用switch-case和as判断类型
        for item2 in exampleany {
            switch item2 {
            case let someInt as Int:
                print("整型值为 \(someInt)")
            case let someDouble as Double where someDouble > 0:
                print("Pi 值为 \(someDouble)")
            case let someString as String:
                print("\(someString)")
            case let phy as Chemistry:
                print("主题 '\(phy.physics)', \(phy.equations)")
            default:
                print("None")
            }
        }
        
        
        // MARK:- 模块扩展的使用
        4.topic {
            print("=== extension ")
        }
        
        print("".date())
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


// MARK:- 构造器的重载
// 构造器的重载
class Shape {
    var corner : Int = 0
}

class Circle : Shape {
    var radius : Int
    override init() {
        self.radius = 10
        super.init()
        super.corner = 1
    }
    
    // 可失败构造器，如果调价不满足返回nil值
    init?(radius: Int) {
        if radius == 0 {
            return nil;
        }
        self.radius = radius
    }
}

// MARK:- 可选链
class Person {
    var residence: Residence?
}

// 定义了一个变量 rooms，它被初始化为一个Room[]类型的空数组
class Residence {
    var rooms = [Room]()
    var numberOfRooms: Int {
        return rooms.count
    }
    subscript(i: Int) -> Room {
        return rooms[i]
    }
    func printNumberOfRooms() {
        print("房间号为 \(numberOfRooms)")
    }
    var address: Address?
}

// Room 定义一个name属性和一个设定room名的初始化器
class Room {
    let name: String
    init(name: String) { self.name = name }
}

// 模型中的最终类叫做Address
class Address {
    var buildingName: String?
    var buildingNumber: String?
    var street: String?
    func buildingIdentifier() -> String? {
        if (buildingName != nil) {
            return buildingName
        } else if (buildingNumber != nil) {
            return buildingNumber
        } else {
            return nil
        }
    }
}


// MARK:- 循环引用->弱引用和无主引用
class Module {
    let name: String
    init(name: String) { self.name = name }
    var sub: SubModule?
    deinit {
        print("\(name) 主模块 deinit")
    }
}

class SubModule {
    let number: Int
    
    init(number: Int) { self.number = number }
    
    weak var topic: Module?
    
    deinit {
        print("子模块 topic 数为 \(number) deinit")
    }
}

// MARK:- 闭包导致的循环引用
class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        // 使用无主引用解决闭包的循环引用问题
        // FIXME: 使用无主引用解决闭包的循环引用问题
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("HTMLElement # \(name) 被析构")
    }
}


// MARK:- 类型检查
class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}


// MARK:- 扩展
extension Int {
    func topic(sum:() -> ()) {
        for _ in 1...self {
            sum()
        }
    }
}

extension String {
    func date() -> NSDate {
        return NSDate()
    }
}


